Shader "Studio/URP-YoFi/Character/Character-Toon-div" 
{
	Properties
	{
		_MainColorTint("Main Color Tint", color) = (1,1,1,1)
//		_AmbientEffectFactor("Ambient Effect Factor", Range(0,1)) = 1
//		
//		_DarkColor("Dark Color", color) = (0.5,0.5,0.5,1)
//		_LambertMin ("Lambert Min", Range(0,1)) = 0
//		_LambertMax ("Lambert Max", Range(0,1)) = 1
//		_FresnelMin ("Fresnel Min", Range(0,1)) = 0
//		_FresnelMax ("Fresnel Max", Range(0,1)) = 1
//		[HDR]_FresnelColor("Fresnel Color", color) = (0.4,0.4,0.4,1)
//        _SupLightDir("SupLight Dir", Vector) = (-0.891, 0.454, 0.00,0)
		
		[Toggle]_UseSplitUV("Use Split UV", Float) = 0
		_SplitID("Split ID",Range(0,3)) = 0

		_MainTex ("Main Tex", 2D) = "white" {}
		_DarkTex ("Dark Tex", 2D) = "black" {}
		_DataTex ("Data Tex", 2D) = "white" {}
        // [Header(Hair)]
        // /*
        //     前端使用：（我只给我想到的）
        //     通过GetFloat("_IsToning")  因为这个需要贴图支持，所以应该是美术管理开启与否。
        //     SetColor("_warmColor") SetColor("_coolColor") 这里程序赋值
        // */
        // [Toggle]_IsToning("开启调色模式", Float) = 0
        // _warmColor("暖色调", color) = (0.8,0.2,0.2,0.5)
        // _coolColor("冷色调", color) = (0.0,0.5,0.0,0.5)
		// _touPiTex ("颜色补偿贴图", 2D) = "white" {}       
 
        [Header(OutLine)]
		_OutlineWidth("_OutlineWidth", float) = 1
        _OutlineTint("_OutlineTint", color) = (0.4,0.4,0.4,1)

        [Header(Shadow)]
        _ShadowColor("Shadow Color", color) = (0.0,0.0,0.0,0.5)
        
	}

	SubShader 
	{
		Tags
		{
			"RenderType" = "Opaque"
            "Queue" = "Geometry"
		}
		
		HLSLINCLUDE
		
		#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
		#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
		#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
		
		TEXTURE2D(_MainTex);
		//SAMPLER(sampler_MainTex);
		TEXTURE2D(_DarkTex);
		TEXTURE2D(_DataTex);
		TEXTURE2D(_RMATex);
        TEXTURE2D(_touPiTex);
		SAMPLER(sampler_RMATex);
        TEXTURE2D (_NormalTex);
        SAMPLER(sampler_NormalTex);

		SAMPLER(sampler_linear_repeat);
        SAMPLER(sampler_linear_clamp);
        SAMPLER(sampler_point_repeat);


		float3 _CharaMainColorTint;
		float3 _CharaDarkColorTint;


		CBUFFER_START(UnityPerMaterial)
		float3 _MainColorTint;
		float _AmbientEffectFactor;

        float4 _warmColor, _coolColor;
        float _IsToning;

		float4 _DarkColor;
		float _LambertMin;
		float _LambertMax;
		float _FresnelMin;
		float _FresnelMax;
		float3 _SupLightDir;
		float3 _FresnelColor;

		float4 _NormalTex_ST;
        //float _BakedLightIntensity;
        float _NormalScale;
		float _Metallic;
		float _Roughness;

		float _UseSplitUV;
		float _SplitID;

		float _OutlineWidth;
        float3 _OutlineTint;
		CBUFFER_END
		        
		ENDHLSL

		Pass
		{
			HLSLPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			// #pragma multi_compile _ _MAIN_LIGHT_SHADOWS 
			// #pragma multi_compile _ _SHADOWS_SOFT
			#define _MAIN_LIGHT_SHADOWS true
			#define _SHADOWS_SOFT true
			// #pragma multi_compile _ LIGHTMAP_ON
			//#pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
            //#pragma multi_compile _ SHADOWS_SHADOWMASK
			//#pragma multi_compile _ CALCULATE_BAKED_SHADOWS
			
			

			struct Attributes
			{
				float4 positionOS : POSITION;
				float3 normalOS     : NORMAL;
				float2 uv : TEXCOORD0;
				float2 uv2 : TEXCOORD1;
                float4 tangentOS : TANGENT;

			};

			struct Varyings
			{
				float4 positionHCS : SV_POSITION;
				float2 uv : TEXCOORD0;
				float2 uv2 : TEXCOORD1;
				float3 positionWS : TEXCOORD2;
				float3 normalWS  : TEXCOORD3;
                float3 tangentWS :TEXCOORD4;
                float3 BtangentWS : TEXCOORD5;

                float4 screenPos : TEXCOORD6;

				DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH,7);

			};

            inline float3 DT_PS_OVERLAY(float4 _layer0, float4 _layer1)
            {
                const float3 layer0 = _layer0.rgb * _layer0.a;
                const float3 layer1 = _layer1.rgb * _layer1.a;
                // 预先计算 layer0 和 layer1 的最大值，减少重复计算
                const float layer0Max = max(layer0.r, max(layer0.g, layer0.b));
                // 计算步进值，判断 layer0 的最大值是否大于 0.5
                const float stepValue = step(0.5, layer0Max);
                float3 twoLayer0Layer1 = 2.0 * layer0 * layer1;
                float3 oneMinusLayer0 = 1.0 - layer0;
                float3 oneMinusLayer1 = 1.0 - layer1;
                float3 oneMinusTwoOneMinusLayer0OneMinusLayer1 = 1.0 - 2.0 * oneMinusLayer0 * oneMinusLayer1;
                // 使用 lerp 函数进行插值计算
                return lerp(twoLayer0Layer1, oneMinusTwoOneMinusLayer0OneMinusLayer1, stepValue);
            }

			Varyings vert (Attributes IN)
			{
				Varyings OUT;
				OUT.uv = IN.uv;
				OUT.uv2 = IN.uv2;
				OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
				OUT.positionWS = TransformObjectToWorld(IN.positionOS.xyz);
                OUT.normalWS = TransformObjectToWorldNormal(IN.normalOS).xyz;
                OUT.tangentWS = TransformObjectToWorldDir(IN.tangentOS.xyz);
                OUT.BtangentWS = cross(OUT.normalWS.xyz,OUT.tangentWS.xyz) * IN.tangentOS.w * unity_WorldTransformParams.w;

				OUT.screenPos = ComputeScreenPos(OUT.positionHCS);

                OUTPUT_LIGHTMAP_UV(IN.uv2, unity_LightmapST, OUT.lightmapUV);
                OUTPUT_SH(OUT.normalWS, OUT.vertexSH);
				return OUT;
			}

           

             

			half4 frag (Varyings IN) : SV_Target
			{

				float3 positionWS = IN.positionWS;
                float3 viewDirectionWS = normalize(_WorldSpaceCameraPos.xyz - positionWS);
                float3 normalWS = SafeNormalize(IN.normalWS);
                float3 tangentWS = SafeNormalize(IN.tangentWS);
                float3 bitTangentWS = SafeNormalize(IN.BtangentWS);

                float3 testValue = 0;
				float2 splitedUV = IN.uv;
				if(_UseSplitUV)
				{
					float id = round(_SplitID);
					float columnRef = 2.0f;
					float rowRef = 2.0f;
					float row = floor( id / columnRef);
					float column = fmod(id , rowRef);
					
					splitedUV = IN.uv.xy / float2(columnRef,rowRef) + float2(column,row) / float2(columnRef,rowRef);
				}
				
				
				half4 dataTex = SAMPLE_TEXTURE2D(_DataTex, sampler_linear_repeat, IN.uv);


                half4 darkTex = SAMPLE_TEXTURE2D(_DarkTex, sampler_point_repeat, splitedUV);
                half4 mainTex = SAMPLE_TEXTURE2D(_MainTex, sampler_linear_repeat, splitedUV);

                  
                half3 mainColor = mainTex.rgb * _MainColorTint;
                darkTex.rgb = lerp(mainTex.rgb ,mainTex.rgb * darkTex.rgb , darkTex.a); 
                
                             
                Light mainLight =  GetMainLight();//获取主光源
                half3 ambient = mainLight.color.rgb + _AmbientEffectFactor * _GlossyEnvironmentColor.rgb;
             
                half3 finalColor = mainColor  *  ambient;

				float3x3 TBN = float3x3(tangentWS, bitTangentWS, normalWS);
                float3 normalTex  = UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalTex, sampler_linear_repeat, IN.uv),_NormalScale);
                normalWS = normalize(mul(normalTex, TBN));

				float ndotv = dot( normalWS,viewDirectionWS )*2;
                float3 normaltemp =  normalWS * ndotv - viewDirectionWS;
                float3 normalView = mul((float3x3)GetWorldToViewMatrix(), normaltemp).xyz;
                normalView = normalize(normalView);
                //float3 normalView = TransformWorldToViewDir(normalWS,true);
                float3 normalView01 = normalView * 0.5 + 0.5;

				
                float lambert = dot(normalWS,mainLight.direction);
                lambert = lambert * 0.5 + 0.5;
				
				float ramp = smoothstep(  0.48,0.5 ,saturate(lambert * mainLight.shadowAttenuation) );
                
                        
				finalColor = lerp(darkTex.rgb ,mainTex.rgb , ramp * dataTex.r);

				// finalColor = lerp(_OutlineTint.rgb * darkTex.rgb,finalColor, dataTex.g);

				//finalColor = mainTex.rgb * ramp;
				
				// float fresnel = smoothstep(  _FresnelMin,_FresnelMax ,normalView01.z );
				// float supLightMask = dot( normalView , normalize(_SupLightDir.xyz));
				// supLightMask = clamp(supLightMask, 0, 1);
    //             fresnel = min(supLightMask,fresnel);
				// float3 fresnelColor = fresnel * _FresnelColor.rgb;
				
				//finalColor += fresnelColor;

				
				return half4(finalColor,1.0);
			}
			ENDHLSL 
		}

		Pass
        {
            Name "Outline"
            Tags { "LightMode" = "OutlinePass" }
            Cull Front
            ZTest On
            ZWrite On

            HLSLPROGRAM

            #pragma vertex vert
            #pragma fragment frag

         
            struct Attributes
            {
                float4 color : COLOR;
                float2 uv0 : TEXCOORD0;
                float4 vertex : POSITION;
                float4 normal : NORMAL;
                float4 tangent : TANGENT;
            }; 

            struct Varyings
            {
                float4 positionHCS : SV_POSITION;
                float2 uv : TEXCOORD0;
            	float3 positionWS : TEXCOORD1;
            	float3 normalWS : TEXCOORD2;
            };

            Varyings vert(Attributes v)
            {
                Varyings OUT;

                float4 scaledScreenParams = GetScaledScreenParams();
                float ScaleX = abs(scaledScreenParams.x / scaledScreenParams.y);

                OUT.positionHCS = TransformObjectToHClip(v.vertex.xyz);
                OUT.positionWS = TransformObjectToWorld(v.vertex.xyz);

                float3 tangentOS = v.tangent.xyz;
                float3 normalOS = v.normal.xyz;
                float3 biTangentOS = cross(normalOS, tangentOS) * v.tangent.w * GetOddNegativeScale();

                float3 smoothNormalTS = v.color.rgb * 2 - 1;
                float3x3 TBN_TSOS= float3x3(tangentOS, biTangentOS, normalOS);

                float3 smoothNormalOS = mul(smoothNormalTS, TBN_TSOS);
                smoothNormalOS = SafeNormalize(smoothNormalOS);
                normalOS = smoothNormalOS;

                _OutlineWidth *= v.color.a;

                OUT.normalWS = TransformObjectToWorldNormal(normalOS);
                float3 normalCS = TransformWorldToHClipDir(OUT.normalWS);
                float2 extend = normalize(normalCS.xy) * (_OutlineWidth*0.01); 
                extend.x /= ScaleX;


                //裁剪空间描边，可以使得相机远近描边宽度一致，和屏幕空间等宽边缘光思路一致
            	//_OutlineClampScale = 1 
                float ctrl = clamp(1/(OUT.positionHCS.w + 1),0,1);
                OUT.positionHCS.xy += extend * OUT.positionHCS.w * ctrl;
            	//OUT.positionHCS.xy += min(1.0 , OUT.positionHCS.w) * extend.xy;

                OUT.uv = v.uv0;
                return OUT;
            }
            
            float4 frag (Varyings IN) : SV_Target
            {
                half4 darkTex = SAMPLE_TEXTURE2D(_DarkTex,sampler_linear_repeat,IN.uv);
                return half4(_OutlineTint.xyz * darkTex.rgb , 1);
            }
            
            ENDHLSL
        }

		Pass
        {
			Name "MeshShadow"
			Tags
			{
				"LightMode" = "MeshShadow"  
				"Queue" = "Transparent" 
				"IgnoreProjector" = "True" 
				"RenderType" = "Transparent"
			}

			Blend SrcAlpha OneMinusSrcAlpha
			ZWrite Off
			Stencil
            {
                Ref 1
                Comp NotEqual
                Pass Replace
            }
            HLSLPROGRAM
            #pragma vertex vertShadow
            #pragma fragment fragShadow 

            float4 _ShadowColor;
            
            struct appdataShadow
            {
                float4 vertex : POSITION;
            };

            struct v2fShadow
            {
                float4 positionCHS : SV_POSITION;
				float3 positionWS : TEXCOORD0;
                float3 originWS : TEXCOORD1;
            };


            v2fShadow vertShadow (appdataShadow v)
            {
                v2fShadow o;
            	float _ShadowAngle = 0;//0.39;
	            float _ShadowLength = 1.5;
                Light mainLight =  GetMainLight();//获取主光源 
                float3 d = -mainLight.direction;
                float2 dd = normalize(float2(d.x,d.z));

            	
                float4 worldPos = mul(unity_ObjectToWorld,v.vertex);
                float4 originWS = mul(unity_ObjectToWorld,float4(0,0,0,1));
                float angle =  _ShadowAngle * 3.1415926*2;
                float x1 = cos(angle);
                float y1 = sin(angle);
                float offsetValue = worldPos.y * _ShadowLength;
                worldPos.xz += float2(d.x,d.z) * offsetValue;
                worldPos.y = 0.001;
                o.originWS = originWS.xyz;
                o.positionWS = worldPos.xyz;
                o.positionCHS = TransformWorldToHClip(worldPos.xyz);
                return o;
            }

            half4 fragShadow (v2fShadow i) : SV_Target
            {
            	float4 shadowColor =  _ShadowColor ;//half4(0,0,0,0.5);
	            float _ShadowLength = 1.5;
	            float _FadeOffset = 0.8;

            	
				half4 col = shadowColor;
                float length = distance(i.positionWS,i.originWS);

                float fade = length / _ShadowLength - _FadeOffset;
                fade = 1 - saturate(fade);
				col.a *= fade;
                //col = float4(fade,fade,fade,1);
                return col;
            }
            ENDHLSL
        }

		Pass
        {
            Name "DepthOnly"
            Tags{"LightMode" = "DepthOnly"}

            ZWrite On
            ColorMask r
            Cull Back

            HLSLPROGRAM
            #pragma only_renderers gles gles3 glcore d3d11
            #pragma target 2.0
            #pragma vertex DepthOnlyVertex
            #pragma fragment DepthOnlyFragment
            // Material Keywords
            //#pragma shader_feature_local_fragment _ALPHATEST_ON
            //#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
            // GPU Instancing
            // #pragma multi_compile_instancing

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            struct Attributes
            {
                float4 position     : POSITION;
                float2 texcoord     : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4 positionCS   : SV_POSITION;
                float2 uv           : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
                UNITY_VERTEX_OUTPUT_STEREO
            };

            Varyings DepthOnlyVertex(Attributes input)
            {
                Varyings output = (Varyings)0;
                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
                //output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
                output.uv = input.texcoord;

                output.positionCS = TransformObjectToHClip(input.position.xyz);
                return output;
            }

            half4 DepthOnlyFragment(Varyings input) : SV_TARGET
            {
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);


                return half4(0,0,0,1);
            }
            ENDHLSL
        }

        

       

		Pass 
        {
            Name "ShadowCaster"
            Tags{ "LightMode" = "ShadowCaster" }
            Cull Back

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag


            struct a2v {
                float4 vertex : POSITION;
                //float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
            };
            struct v2f {
                float4 vertex : SV_POSITION;
                //float2 uv : TEXCOORD0;
            };

            v2f vert(a2v v)
            {
                v2f o = (v2f)0;
                float3 worldPos = TransformObjectToWorld(v.vertex.xyz);
                half3 normalWS = TransformObjectToWorldNormal(v.normal);
                Light mainLight =  GetMainLight();//获取主光源

                worldPos = ApplyShadowBias(worldPos, normalWS, mainLight.direction);
                o.vertex = TransformWorldToHClip(worldPos);
                //o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }
            real4 frag(v2f i) : SV_Target
            {
//#if _ALPHATEST_ON
//                half4 col = tex2D(_MainTex, i.uv);
//                clip(col.a - 0.001);
//#endif
                return 0;
            }
            ENDHLSL
        }
	}
}